package DeportManage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Map;
import java.util.Scanner;

public class DepotManager {
	private CustomerList customerList; // the list of customers
	private ParcelList parcelList; // the list of parcels
	private ArrayList<String> recieptList; // the list of receipts for collecting parcel	
	private double total_fee;// the total fee in one day
	/**
	 * Constructor to create an object with Customer-List, Parcel-List and Reciept-List
	 */
	public DepotManager(){
		total_fee = 0;
		customerList = new CustomerList();
		parcelList = new ParcelList();
		recieptList = new ArrayList<String>();
	}
	/**
	 * Method to write the final report to the specific file(FinalReport.txt)
	 * @param filename String the name of file for writing
	 * @param finalreport String the final report of "Depot Simulator" System
	 */
	public void writeToFile(String filename){
		FileWriter Fw;
		String final_report = this.getFinalReport();
		try{
			 Fw=new FileWriter(filename);
             Fw.write("The Final Report of Assignment 1\n");             
             Fw.write(final_report);
             Fw.close();
		}
		catch(FileNotFoundException fNF){// boolean whether there is the file.
             System.out.println("The out file, " +filename + ", is not found! ");
             System.exit(0);
        }
		catch(IOException iOE){// all of other IO errors
             iOE.printStackTrace();
             System.exit(1);
		}
	}
	/**
	 * Method to read the specific file(Customerlist.txt or Parcellist.txt)
	 * @param filename String the name of file for reading
	 */
	@SuppressWarnings("resource")
	public void readFromFile(String filename){
		try{
			File inputFile = new File(filename);
			Scanner sc=new Scanner(inputFile);
			if(filename == "CustomerList.txt"){// read data from the txt file "Customerlist.txt"
				while(sc.hasNextLine()){
					String readingLine = sc.nextLine();
					if (readingLine.length() != 0)
						readbyLineforCustomer(readingLine);// read the data line-by-line
				}
			}
			else if(filename == "ParcelList.txt"){// read data from the txt file "Parcellist.txt"
				while(sc.hasNextLine()){
					String readingLine = sc.nextLine();	
					if (readingLine.length() != 0)
						readbyLineforParcel(readingLine);// read the data line-by-line
				}
			}				
		}
		catch(FileNotFoundException fnf){//boolean whether there is the file.
			System.out.println("The input file, " +filename + ", is not found! ");
            System.exit(0);
		}
	}
	/**
	 * Method to collect the data line-by-line and put into Customer List
	 * @param readingLine String a line of data from data file
	 */
	public void readbyLineforCustomer(String readingLine){
		try{
			int sequenceNo = 1;
			String customerstring [] = readingLine.split(",");
			Name name = new Name(customerstring[0]);
			
			
			if(!customerList.getCustomerList().isEmpty()){	
				int indexOfLastObject = customerList.getSize()-1;
				Customer lastCustomer = customerList.getCustomerList().get(indexOfLastObject);
				sequenceNo = lastCustomer.getSequenceNo()+1;
			}
			
			String id_parcel = customerstring[1];
			
			@SuppressWarnings("unused")
			int numberOfID = Integer.parseInt(id_parcel.substring(1));
			
			Customer customer = new Customer(sequenceNo,name,id_parcel);
			customerList.addCustomer(customer);		
		}
		catch(ArrayIndexOutOfBoundsException oae){
			System.out.println(oae.getMessage());
			System.exit(0);
		} catch (ErrorFormatNameException efne) {
			System.out.println(efne.getMessage());
			System.exit(0);
		} catch (DuplicateException de) {
			System.out.println(de.getMessage());
			System.exit(0);
		} catch (NotFormatParcelIDException nfpie) {
			System.out.println(nfpie.getMessage());
			System.exit(0);
		}
	}
	/**
	 * Method to collect the data line-by-line and put into Parcel List
	 * @param readingLine String a line of data from data file
	 */
	public void readbyLineforParcel(String readingLine){
		String id_parcel ="";
		int days = 0;
		double weight = 0;
		double width = 0;
		double length = 0;
		double height = 0;
		try{
			String parcelstring [] = readingLine.split(",");

			@SuppressWarnings("unused")
			int numberOfID = Integer.parseInt(parcelstring[0].substring(1));
			
			id_parcel = parcelstring[0];
			days = Integer.parseInt(parcelstring[1]);
			weight = Double.parseDouble(parcelstring[2]);
			String dimension [] = parcelstring[3].split("x");
			width = Double.parseDouble(dimension[0]);
			length = Double.parseDouble(dimension[1]);
			height = Double.parseDouble(dimension[2]);
			Parcel parcel = new Parcel(id_parcel,days,weight,height,width,length);
			parcelList.addParcel(parcel);			
		}
		catch(NumberFormatException nfe){
			System.out.println(nfe.getMessage());
			System.exit(0);
		}
		catch(ArrayIndexOutOfBoundsException oae){
			System.out.println("The readling is out of BOUND: " + readingLine);
			System.exit(0);
		} catch (NotFormatParcelIDException nfpie) {
			System.out.println(nfpie.getMessage());
			System.exit(0);
		} catch (OutRangeOfDaysException orode) {
			System.out.println(orode.getMessage());
		} catch (DuplicateException de) {
			System.out.println(de.getMessage());
		}
	}
	/**
	 * Method to process customers' collection one by one.
	 * @throws NotFoundParcelIDException 
	 */
	public void performQueue() throws NotFoundParcelIDException{
		try {
			int size = customerList.getSize();
			int sequence_No = 1;
			while(sequence_No <= size){
				Customer customer_processing = customerList.searchCustomerBySequenceNo(sequence_No);
				String parcelID = customer_processing.getParcelID();
				processCollection(customer_processing);
				customerList.removeCustomer(customer_processing);				
				sequence_No++;
			}
		}
		catch (NotFoundCustomerByNoException nfcbie) {
			System.out.print(nfcbie.getMessage());
			System.exit(0);
		}	
	}
	/**
	 * /**
	 * Method to process the collection of parcels of customers in qeue
	 * @param cm Customer the customer in collection processing 	 
	 */
	public void processCollection(Customer cm) {
		try {
			int sequence_no = cm.getSequenceNo();
			String name = cm.getName().getFullName();	
			String parcelID = cm.getParcelID();
			
			Parcel parcel_collecting = parcelList.searchParcelByParcelID(parcelID);
			int days = parcel_collecting.getDays();
			double weight = parcel_collecting.getWeight();
			double width = parcel_collecting.getWidth();
			double height = parcel_collecting.getHeight();
			double length = parcel_collecting.getLength();
			String dimension = parcel_collecting.getDimension();		
			
			// Calculate the total cost of specific parcel 
			Calculation calculation_cost = new Calculation(days,weight,height,width,length);
			double total_cost = calculation_cost.getCost();
			this.total_fee += total_cost;		
			
			// generate the receipt for specific parcel	
			String receipt = printReceipt(parcelID,days,weight,dimension,total_cost,sequence_no,name);
			System.out.println(receipt);
			recieptList.add(receipt);

			parcelList.removeParcelByParcelID(parcelID);
			
		} catch (NotFoundParcelIDException nfpie) {
			System.out.print(nfpie.getMessage());
		}
	
	}
	/**
	 * Method to generate the receipt with all of details
	 * @param id String the unique ID of parcel
	 * @param days int the number of days
	 * @param weight double the weight of parcel(kg)
	 * @param dimenssion String the dimension of parcel
	 * @param total_cost double the total cost of specific parcel 
	 * @param no_sequence the sequence number of specific parcel owner
	 * @param name String the name of specific parcel owner 
	 * @return String the receipt of collection of specific parcel
	 */
	public String printReceipt(String id, int days, double weight, String dimension,
			double total_cost, int sequence_no, String name){
		// get the current time 
		String now=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());
		// generate receipt 
		String receipt = "Sequence No. " + sequence_no + "    Name: " + name + "      Date: " + now +"\n"; 
		receipt += "Parcel ID    Number of Days     Weight     Dimension        Fee \n"; 
		receipt += String.format("%-14s", id);
		receipt += String.format("%-18s", days); 
		receipt += String.format("%-11s", weight);
		receipt += String.format("%-17s", dimension); 
		receipt += String.format("%-4s", total_cost);	
		return receipt;
	}
	/**
	 * Method to generate lists of uncollected parcels and their owners
	 * @return String lists of uncollected parcels and their owners
	 */
	public String getUncollectedList(){
		String list="\n";		
		list +="UNCOLLECTED LISTS\n";
		
		// get the list of Parcel
		list +="The List of Parcels:\n";
		list +="Parcel ID    Days   Weight     Dimension    \n";
		for(Map.Entry<String, Parcel> parcel : parcelList.getParcel().entrySet()){
			list += String.format("%-14s", parcel.getValue().getID());
			list += String.format("%-8s", parcel.getValue().getDays());
			list += String.format("%-9s", parcel.getValue().getWeight());
			list += String.format("%-13s", parcel.getValue().getDimension());
			list += "\n";
		}		
		return list;
	}
	/**
	 * Method to print out the final report of "Depot Simulator" System for a day
	 * @return String final report of "Depot Simulator" System
	 */
	public String getFinalReport(){
		String final_report = getUncollectedList() +"\n\n\n"+"The Receipts"+"\n";
		final_report += "The Count of Receipts: " + recieptList.size()+"\n\n"; 
		if(recieptList != null){
			for(String receipt : recieptList){
				final_report += receipt + "\n\n";
			}		
		}
		final_report += "\n";
		final_report +=  "\n";
		
		//Keep two decimal places
		total_fee = (double)Math.round(total_fee * 100) / 100;
		final_report += "Total Fee: " + String.valueOf(total_fee);
		
		return final_report;
	}
}